import pyaudio
import threading
import wave

from datetime import datetime
from pathlib import Path
from time import sleep


class Recorder:
    def __init__(self, translation_service, device_index=None, save_recording=False):
        self.translation_service = translation_service
        self.pa = None
        self.stream = None
        self.is_recording = False
        self.device_index = device_index  # 指定麦克风设备索引
        self.save_recording = save_recording  # 是否保存录音到本地
        self.audio_frames = []  # 用于存储录音数据
        self.chunk_size = 3200  # 每次读取3200字节，对应100ms音频（16kHz，16bit，单声道）
        self.format = pyaudio.paInt16
        self.channels = 1
        self.rate = 16000
        self._stopped = False  # 添加一个标志，确保stop_recording只被调用一次
        self._lock = threading.Lock()  # 添加线程锁
    
    @staticmethod
    def get_available_devices():
        """获取所有可用的麦克风设备，过滤掉非麦克风设备"""
        devices = []
        pa = pyaudio.PyAudio()
        
        for i in range(pa.get_device_count()):
            info = pa.get_device_info_by_index(i)
            # 筛选输入设备
            if info["maxInputChannels"] > 0:
                device_name = info["name"]

                # 检查设备名称是否包含麦克风关键词
                mic_keywords = ["麦克风", "Mic", "Microphone", "话筒", "Voice"]
                has_mic_keyword = any(keyword in device_name for keyword in mic_keywords)
                
                # 如果设备名称不包含非麦克风关键词，或者包含麦克风关键词，则认为是麦克风
                if has_mic_keyword:
                    devices.append({
                        "index": i,
                        "name": device_name
                    })
        
        pa.terminate()
        return devices
    
    def start_recording(self):
        self.is_recording = True
        threading.Thread(target=self._record_loop, daemon=True).start()
    
    def _start_saving(self):
        """开始保存录音"""
        try:
            self.audio_frames = []
            # 创建录音文件保存目录
            output_dir = "recordings"
            if not Path(output_dir).exists():
                Path(output_dir).mkdir(parents=True)
            
            # 生成带时间戳的文件名
            timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
            filename = Path(output_dir) / f"recording_{timestamp}.wav"
            
            # 创建WAV文件
            wf = wave.open(str(filename), 'wb')
            wf.setnchannels(self.channels)
            wf.setsampwidth(self.pa.get_sample_size(self.format))
            wf.setframerate(self.rate)

            while self.is_recording:
                tmp = self.audio_frames
                self.audio_frames = []
                if len(tmp) > 0:
                    wf.writeframes(b''.join(tmp))
                sleep(1)
            wf.close()
            
            print(f"录音已保存到: {filename}")
        
        except Exception as e:
            print(f"保存录音失败: {e}")
        finally:
            # 清空音频数据
            self.audio_frames = []
    
    def stop_recording(self):
        with self._lock:
            if self._stopped:
                return  # 如果已经停止，直接返回
            self._stopped = True
        
        try:
            self.is_recording = False
            if self.stream:
                self.stream.stop_stream()
                self.stream.close()
                self.stream = None
            if self.pa:
                self.pa.terminate()
                self.pa = None
        except Exception as e:
            print(f"停止录音失败: {e}")
    
    def _record_loop(self):
        self.pa = pyaudio.PyAudio()
        
        # 打印所选设备信息
        if self.device_index is not None:
            device_info = self.pa.get_device_info_by_index(self.device_index)
            print(f"使用麦克风: {device_info['name']} (索引: {self.device_index})")
        else:
            print("使用默认麦克风")
        
        self.stream = self.pa.open(
            format=self.format,
            channels=self.channels,
            rate=self.rate,
            input=True,
            input_device_index=self.device_index,
            frames_per_buffer=self.chunk_size
        )
        
        print("开始录音")
        if self.save_recording:
            threading.Thread(target=self._start_saving, daemon=True).start()
        while self.is_recording:
            try:
                data = self.stream.read(self.chunk_size, exception_on_overflow=False)
                # 将音频数据发送给翻译服务，检查translation_service是否仍然存在
                if hasattr(self, 'translation_service') and self.translation_service:
                    self.translation_service.send_audio(data)
                # 如果需要保存录音，将数据添加到列表
                if self.save_recording:
                    self.audio_frames.append(data)
            except Exception as e:
                print(f"录音出错: {e}")
                break
        
        print("停止录音")
        # 确保stop_recording只被调用一次
        self.stop_recording()
